﻿using Castle.DynamicProxy;
using EventHandlerDemo.Domain.Bases;

namespace EventHandlerDemo.Infrastructure.Interceptors
{
    public class UowTransactionAsyncInterceptor : IAsyncInterceptor
    {
        private readonly IUnitOfWork _unitOfWork;

        public UowTransactionAsyncInterceptor(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

        public void InterceptSynchronous(IInvocation invocation)
        {
            throw new NotImplementedException();
        }

        public void InterceptAsynchronous(IInvocation invocation)
        {
            throw new NotImplementedException();
        }

        public void InterceptAsynchronous<TResult>(IInvocation invocation)
        {
            Console.WriteLine($"Executing {invocation.Method.Name} with parameters: " + string.Join(", ", invocation.Arguments.Select(a => a?.ToString()).ToArray()));
            invocation.ReturnValue = InternalInterceptAsynchronous<TResult>(invocation);
            Console.WriteLine($"Finished executing {invocation.Method}");
        }

        private async Task<TResult> InternalInterceptAsynchronous<TResult>(IInvocation invocation)
        {
            TResult result;

            try
            {
                _unitOfWork.BeginTransaction();

                invocation.Proceed();
                var task = (Task<TResult>)invocation.ReturnValue;
                result = await task;

                await _unitOfWork.CommitAsync();
            }
            catch (Exception)
            {
                await _unitOfWork.RollbackAsync();
                throw;
            }
            finally
            {
                _unitOfWork.Dispose();
            }

            return result;
        }
    }
}
